package com.itheima.sfbx.insurance.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.sfbx.framework.commons.constant.basic.SuperConstant;
import com.itheima.sfbx.framework.commons.constant.insure.InsureConstant;
import com.itheima.sfbx.framework.commons.dto.basic.TreeItemVO;
import com.itheima.sfbx.framework.commons.dto.basic.TreeVO;
import com.itheima.sfbx.framework.commons.exception.ProjectException;
import com.itheima.sfbx.framework.commons.utils.BeanConv;
import com.itheima.sfbx.framework.commons.utils.EmptyUtil;
import com.itheima.sfbx.framework.commons.utils.ExceptionsUtil;
import com.itheima.sfbx.framework.commons.utils.NoProcessing;
import com.itheima.sfbx.insurance.dto.CategoryCoefficentVO;
import com.itheima.sfbx.insurance.dto.CategoryConditionVO;
import com.itheima.sfbx.insurance.dto.CategorySafeguardVO;
import com.itheima.sfbx.insurance.dto.CategoryVO;
import com.itheima.sfbx.insurance.enums.CategoryEnum;
import com.itheima.sfbx.insurance.mapper.CategoryMapper;
import com.itheima.sfbx.insurance.pojo.Category;
import com.itheima.sfbx.insurance.service.ICategoryCoefficentService;
import com.itheima.sfbx.insurance.service.ICategoryConditionService;
import com.itheima.sfbx.insurance.service.ICategorySafeguardService;
import com.itheima.sfbx.insurance.service.ICategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description：保险分类服务实现类
 */
@Slf4j
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements ICategoryService {

    @Autowired
    ICategoryConditionService categoryConditionService;

    @Autowired
    ICategoryCoefficentService categoryCoefficentService;

    @Autowired
    ICategorySafeguardService categorySafeguardService;

    private QueryWrapper<Category> queryWrapper(CategoryVO categoryVO) {
        QueryWrapper<Category> lqw = new QueryWrapper<>();
        lqw.eq(StrUtil.isNotBlank(categoryVO.getCategoryNo()),"category_no",categoryVO.getCategoryNo())
                .like(StrUtil.isNotBlank(categoryVO.getCategoryName()), "category_name", categoryVO.getCategoryName())
                .eq(StrUtil.isNotBlank(categoryVO.getDataState()), "data_state", categoryVO.getDataState())
                .eq(StrUtil.isNotBlank(categoryVO.getParentCategoryNo()), "parent_category_no", categoryVO.getParentCategoryNo())
                .eq(StrUtil.isNotBlank(categoryVO.getCheckRule()), "check_rule", categoryVO.getCheckRule());
        return lqw;
    }
    @Override
    public Page<CategoryVO> findPage(CategoryVO categoryVO, int pageNum, int pageSize) {
        try {
            //构建分页对象
            Page<Category> categoryPage = new Page<>(pageNum,pageSize);
            //构建查询条件
            QueryWrapper<Category> queryWrapper = queryWrapper(categoryVO);
            //查询分页基本列表数据
            Page<Category> page = page(categoryPage, queryWrapper);
            if (EmptyUtil.isNullOrEmpty(page.getRecords())) {
                return null;
            }
            //转换为要返回的VO列表数据
            Page<CategoryVO> resultPage = BeanConv.toPage(page, CategoryVO.class);

            //获取分类列表的每个分类编号放置到一个集合set中
            Set<String> categoryNoSet = page.getRecords().stream().map(Category::getCategoryNo).collect(Collectors.toSet());

        /*处理每个分类的保障项:
        ①根据查询到的分类编号查询出分类下的保障项列表；
        ②对保障项列表根据分类分组；
        ③遍历分类列表设置对应的保障项列表
         */
            List<CategorySafeguardVO> categorySafeguardVOs = categorySafeguardService.findListInCategoryNo(categoryNoSet);
            Map<String, List<CategorySafeguardVO>> categorySafeguardVOMap = categorySafeguardVOs.stream().
                    collect(Collectors.groupingBy(CategorySafeguardVO::getCategoryNo));
            if (!EmptyUtil.isNullOrEmpty(resultPage.getRecords())) {
                resultPage.getRecords().forEach(tmpCategoryVO -> {
                    tmpCategoryVO.setCategorySafeguardVOs(categorySafeguardVOMap.get(tmpCategoryVO.getCategoryNo()));
                });
            }
        /*处理每个分类的系数项:
        ①根据查询到的分类编号查询出分类下的系数项列表；
        ②对系数项列表根据分类分组；
        ③遍历分类列表设置对应的系数项列表
         */
            List<CategoryCoefficentVO> categoryCoefficentVOs = categoryCoefficentService.findListInCategoryNo(categoryNoSet);
            Map<String, List<CategoryCoefficentVO>> categoryCoefficentVOMap = categoryCoefficentVOs.stream().
                    collect(Collectors.groupingBy(CategoryCoefficentVO::getCategoryNo));
            if (!EmptyUtil.isNullOrEmpty(resultPage.getRecords())) {
                resultPage.getRecords().forEach(tmpCategoryVO -> {
                    tmpCategoryVO.setCategoryCoefficentVOs(categoryCoefficentVOMap.get(tmpCategoryVO.getCategoryNo()));
                });
            }
        /*处理每个分类的筛选项:
        ①根据查询到的分类编号查询出分类下的筛选项列表；
        ②对筛选项列表根据分类分组；
        ③遍历分类列表设置对应的筛选项列表
         */
            List<CategoryConditionVO> categoryConditionVOs = categoryConditionService.findListInCategoryNo(categoryNoSet);
            Map<String, List<CategoryConditionVO>> categoryConditionVOMap = categoryConditionVOs.stream().
                    collect(Collectors.groupingBy(CategoryConditionVO::getCategoryNo));
            if (!EmptyUtil.isNullOrEmpty(resultPage.getRecords())) {
                resultPage.getRecords().forEach(tmpCategoryVO -> {
                    tmpCategoryVO.setCategoryConditionVOs(categoryConditionVOMap.get(tmpCategoryVO.getCategoryNo()));
                });
            }

            //返回结果
            return resultPage;
        }catch (Exception e){
            log.error("保险分类分页查询异常：{}", ExceptionsUtil.getStackTraceAsString(e));
            throw new ProjectException(CategoryEnum.PAGE_FAIL);
        }
    }




    @Override
    @Transactional
    public CategoryVO save(CategoryVO categoryVO) {
        //TODO
        return null;
    }

    @Override
    @Transactional
    public Boolean update(CategoryVO categoryVO) {
        //TODO
        return null;
    }

    @Override
    @Transactional
    public Boolean delete(String[] checkedIds) {
        //TODO
        return null;
    }

    @Override
    public List<CategoryVO> findList(CategoryVO categoryVO) {
        //TODO
        return null;
    }



    @Override
    public TreeVO categoryTreeVO(String parentCategoryNo, String categoryType,String[] checkedCategoryNos) {
        //1.确定根节点
        String rootId = StrUtil.isBlank(parentCategoryNo) ? SuperConstant.ROOT_PARENT_ID : parentCategoryNo;
        //2.查询根节点下的子节点
        String processed = NoProcessing.processString(rootId);
        List<Category> list = lambdaQuery()
                .likeRight(Category::getCategoryNo, processed)
                .eq(StrUtil.isNotBlank(categoryType), Category::getCategoryType, categoryType)
                .list();
        if (CollUtil.isEmpty(list)){
            log.error("该No查询不到:{}",parentCategoryNo);
            throw new ProjectException(CategoryEnum.TREE_FAIL);
        }
        //3.1把CategoryList转换为TreeItemVoList
        List<TreeItemVO> treeItemVOS = list.stream().map(ca -> TreeItemVO.builder().id(ca.getCategoryNo()).parentId(ca.getParentCategoryNo()).label(ca.getCategoryName()).build()).collect(Collectors.toList());
        //3.2,1把List集合转成Map,这个map的key是父Id,value是子结点的集合
        Map<String, List<TreeItemVO>> map = treeItemVOS.stream().collect(Collectors.groupingBy(TreeItemVO::getParentId));
        //3.2.2遍历挂关系
        for (TreeItemVO treeItemVO : treeItemVOS) {
            List<TreeItemVO> itemVOS = map.get(treeItemVO.getId());
            treeItemVO.setChildren(itemVOS);
        }
        //4构建这个Vo挂载根节点
        TreeVO treeVO = TreeVO.builder()
                .items(map.get(rootId))
                .build();
        return treeVO;
    }

    @Override
    public String createCategoryNo(String parentCategoryNo) {
        CategoryVO categoryVO = CategoryVO.builder()
            .parentCategoryNo(parentCategoryNo)
            .build();
        QueryWrapper<Category> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Category::getParentCategoryNo,parentCategoryNo);
        List<Category> categoryList = list(queryWrapper);
        //无下属节点则创建下属节点
        if (EmptyUtil.isNullOrEmpty(categoryList)){
            return NoProcessing.createNo(parentCategoryNo,false);
        //有下属节点则累加下属节点
        }else {
            Long categoryNo = categoryList.stream()
                .map(category -> { return Long.valueOf(category.getCategoryNo());})
                .max(Comparator.comparing(i -> i)).get();
            return NoProcessing.createNo(String.valueOf(categoryNo),true);
        }
    }

    /**
     * 人种榜险种榜分类
      * @param type
     */
    @Override
    public List<CategoryVO> categoryCheckRule(String type) {
        //判断是否是险种榜
        if(InsureConstant.checkIsInsureType(type)){
            List<CategoryVO> res = new ArrayList<>();
            //获取所有的险种榜
            List<String> allCheckRule = InsureConstant.getAllCheckRule();
            allCheckRule.forEach(e->{
                CategoryVO categoryVO = CategoryVO.builder().categoryNo(e).categoryName(InsureConstant.getRuleNameById(e)).build();
                res.add(categoryVO);
            });
            return res;
        }else{
            //说明是人种榜
            List<String> categoryNames = Arrays.asList("成年人", "少儿", "老人");
            LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(Category::getCategoryName,categoryNames);
            queryWrapper.eq(Category::getDataState,SuperConstant.DATA_STATE_0);
            List<CategoryVO> res = BeanConv.toBeanList(list(queryWrapper), CategoryVO.class);
            return res;
        }
    }
}
